package com.gitee.wsl.platform.network

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.withContext
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.NetworkInterface

private fun getNetworkInterface(networkConnection: NetworkType): NetworkInterface? = try {

    val wifiNetworkInterfaces: List<String> = listOf("wi-fi", "wireless", "en0", "wlan0", "ap0")
    val ethernetNetworkInterfaces: List<String> = listOf("ethernet", "lan", "en1", "eth0", "eth1")

    NetworkInterface.getNetworkInterfaces().toList()
        .firstNotNullOfOrNull { networkInterface ->
            with(networkInterface.name.lowercase()) {
                when (networkConnection) {
                    NetworkType.WIFI -> {
                        if (wifiNetworkInterfaces.any { contains(it) }) networkInterface else null
                    }
                    NetworkType.ETHERNET -> {
                        if (ethernetNetworkInterfaces.any { contains(it) }) networkInterface else null
                    }
                    else -> null
                }
            }
        }
} catch (error: Throwable) {
    null
}

actual suspend fun NetworkChecker.getInfo(): ConnectionInfo?= withContext(Dispatchers.IO) {
    val networkConnection = getNetworkStatus()
    if(!networkConnection.isConnected) return@withContext null
    val networkType = networkConnection.networkType

    try {
        val networkInterface = getNetworkInterface(networkType) ?: return@withContext null

        var ipv4: String? = null
        var ipv6: String? = null

        for (inetAddress in networkInterface.inetAddresses) {
            //debugLog("getIpAddress inetAddress = $inetAddress")
            if (!inetAddress.isLoopbackAddress && networkInterface.isUp) {
                if (ipv4 == null && inetAddress is Inet4Address) ipv4 = inetAddress.hostAddress?.toString()
                if (ipv6 == null && inetAddress is Inet6Address) ipv6 = inetAddress.hostAddress?.toString()
            }
        }

        return@withContext ConnectionInfo(
            ipv4 = ipv4,
            ipv6 = ipv6,
            //externalIp = getExternalIp()
        )
    } catch (error: Exception) {
        ensureActive()
        //debugLog("getIpInfo networkConnection = $networkConnection", error)
        return@withContext null
    }
}